﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.Serialization;
using OpenComposite.Workflow.Interfaces;
using System.Drawing.Design;
using System.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Collections;

namespace OpenComposite.Workflow
{
	[Designer(typeof(ExtendedCodeActivityDesigner), typeof(IDesigner))]
	[ToolboxBitmap(typeof(resfinder), "OpenComposite.Workflow.Resources.script.png")]
	[DefaultEvent("ExecuteCode")]
	[DisplayName("Code")]
	[ActivityValidator(typeof(ExtendedCodeActivityValidator))]
	public class ExtendedCodeActivity : Activity, ITextActivity, ILogicalActivity
	{
		public static readonly DependencyProperty ExecuteCodeEvent = DependencyProperty.Register("ExecuteCode", typeof(EventHandler), typeof(ExtendedCodeActivity));

		[MergableProperty(false)]
		[Category("Handlers")]
		public event EventHandler ExecuteCode
		{
			add { base.AddHandler(ExecuteCodeEvent, value); }
			remove { base.RemoveHandler(ExecuteCodeEvent, value); }
		}

		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{
			base.RaiseEvent(ExecuteCodeEvent, this, EventArgs.Empty);
			return base.Execute(executionContext);
		}

		#region ITextActivity Members

		public static DependencyProperty TextProperty = DependencyProperty.Register(
			"Text", typeof(string), typeof(ExtendedCodeActivity), new PropertyMetadata(""));
		[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
		[DefaultValue("")]
		[Browsable(true)]
		public string Text
		{
			get
			{
				string text = (string)base.GetValue(ExtendedCodeActivity.TextProperty);
				if ( string.IsNullOrEmpty(text) ) return this.Name;
				return text;
			}
			set { base.SetValue(TextProperty, value); }
		}

		DependencyProperty ITextActivity.GetTextProperty()
		{
			return TextProperty;
		}

		#endregion

		#region ILogicalActivity Members

		#region ActivitiesClass
		public static DependencyProperty ActivitiesClassProperty = DependencyProperty.Register(
			"ActivitiesClass", typeof(object), typeof(ExtendedCodeActivity), new PropertyMetadata(null));
		[Category("Extended")]
		[Browsable(false)]
		public object ActivitiesClass
		{
			get { return base.GetValue(ActivitiesClassProperty); }
			set { base.SetValue(ActivitiesClassProperty, value); }
		}
		#endregion

		#region LogicalActivityName
		public static DependencyProperty LogicalActivityNameProperty =
			DependencyProperty.Register("LogicalActivityName", typeof(string),
										typeof(ExtendedCodeActivity), new PropertyMetadata(null));
		[Browsable(false)]
		[Category("Extended")]
		public string LogicalActivityName
		{
			get { return (string)GetValue(LogicalActivityNameProperty); }
			set { SetValue(LogicalActivityNameProperty, value); }
		}

		#endregion

		#region LogicalActivityId
		public static DependencyProperty LogicalActivityIdProperty =
			DependencyProperty.Register("LogicalActivityId", typeof(int),
										typeof(ExtendedCodeActivity), new PropertyMetadata(null));
		[Browsable(false)]
		[Category("Extended")]
		public int LogicalActivityId
		{
			get { return (int)GetValue(LogicalActivityIdProperty); }
			set { SetValue(LogicalActivityIdProperty, value); }
		}
		#endregion

		#endregion

		#region Class ExtendedCodeActivityValidator
		// nested class to use GetInvocationList<T>(DependencyProperty)
		internal class ExtendedCodeActivityValidator : ActivityValidator
		{
			public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
			{
				ValidationErrorCollection errors = new ValidationErrorCollection();
				ExtendedCodeActivity activity = obj as ExtendedCodeActivity;
				if ( activity != null ) {
					if ( ( activity.GetInvocationList<EventHandler>(ExtendedCodeActivity.ExecuteCodeEvent).Length == 0 ) ) {
						Hashtable hashtable = activity.GetValue(WorkflowMarkupSerializer.EventsProperty) as Hashtable;
						if ( ( hashtable == null ) || ( hashtable["ExecuteCode"] == null ) ) {
							errors.Add(ValidationError.GetNotSetValidationError("ExecuteCode"));
						}
					}
				}
				return errors;
			}
		}
		#endregion
	}

	[ActivityDesignerTheme(typeof(ExtendedCodeActivityTheme))]
	internal class ExtendedCodeActivityDesigner : ExtendedActivityDesigner
	{
	}

	internal class ExtendedCodeActivityTheme : ActivityDesignerTheme
	{
		public ExtendedCodeActivityTheme(WorkflowTheme theme)
			: base(theme)
		{
			this.ForeColor = Color.Black;
			this.BorderColor = Color.Gray;
			this.BorderStyle = DashStyle.Solid;
			this.BackColorStart = Color.FromArgb(255, 244, 244, 244);
			this.BackColorEnd = Color.FromArgb(255, 192, 192, 192);
			this.BackgroundStyle = LinearGradientMode.Horizontal;
		}
	}

	[Serializable]
	internal class ExtendedCodeActivityToolBoxItem : ActivityToolboxItem
	{
		public ExtendedCodeActivityToolBoxItem(Type type)
			: base(type)
		{
			base.DisplayName = "Code (Extended)";
		}

		private ExtendedCodeActivityToolBoxItem(SerializationInfo info, StreamingContext context)
		{
			Deserialize(info, context);
		}

	}
}
